/**
 *
 * Creator: jmdvirus
 */

#ifndef CM_SERVICE_BASE_H
#define CM_SERVICE_BASE_H

#include <pthread.h>
#include <map>
#include <list>

#include "CMLock.h"

//
// 注册的 type 类型由各实现自定义，尽量要细颗粒，一个动作一个 type
// 对应的 args 尽量定义为内部使用的，如果是公用，放在 message 中，不具有很强的公用性（如内部配置），
// 应当放在实现类内部，通过  public 开放出去。仅用于参数传递。
//

// c 注册
typedef int (*cm_service_base_notify_cb)(int type, void *args);

// c++ 注册
class CMServiceBaseFunction
{
  public:
    virtual int notify(int type, void *args) = 0;
};

typedef std::map<int, std::list<cm_service_base_notify_cb >> SERVICE_BASE_CB_C_MAP_LIST_TYPE;
typedef std::map<int, std::list<CMServiceBaseFunction *>> SERVICE_BASE_CB_CPP_MAP_LIST_TYPE;

class CMServiceBaseInterface
{
  public:
    // 几个通用的状态定义，具体实现应当与此 id 分开，如从 1001 开始
    // 各实现中无需要再区分id ，已由类本身隔开。
    // 非状态定义，就另外定义
    typedef enum
    {
        SERVICE_BASE_ST_NONE     = 0,
        SERVICE_BASE_ST_STARTING = 1,
        SERVICE_BASE_ST_STARTED  = 2,
        SERVICE_BASE_ST_STOPPING = 3,
        SERVICE_BASE_ST_STOPPED  = 4,
        SERVICE_BASE_ST_RUN      = 5,
    } ServiceBaseStatus;

    CMServiceBaseInterface(const char *name_);
    virtual ~CMServiceBaseInterface();

    // 一般用于一些初始化操作
    virtual int init()   = 0;
    virtual int deinit() = 0;
    // 一般用于正式启动服务
    virtual int start();
    virtual int stop();
    virtual int ctl(int type, void *args) = 0;
    // 列表，允许多客户注册
    virtual int registerNotify(int type, cm_service_base_notify_cb notify);
    virtual int registerNotify(int type, CMServiceBaseFunction *func);

    virtual int unregisterNotify(int type, cm_service_base_notify_cb notify);
    virtual int unregisterNotify(int type, CMServiceBaseFunction *func);

    int getStatus();

    int privNotify(int type, void *args);

  protected:
    // 子类实现，阻塞运行。由父类线程调用
    // 不建议一个服务有多个线程运行，如确有需要，可自行创建。
    virtual int run() = 0;

    void clear();

    int notify(int type, void *args);

    SERVICE_BASE_CB_C_MAP_LIST_TYPE     cNotifyList;
    SERVICE_BASE_CB_CPP_MAP_LIST_TYPE     cppNotifyList;

    void setStatus(int st);

    bool getExited()
    {
        return exited;
    }

  private:
    friend void *threadServiceBaseRun(void *args);
    pthread_t    pid;
    std::string  name;
    bool         exited;
    int          status;
    CMLock       lock;
};

#endif // CM_SERVICE_BASE_H